/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pop3proxy.persistence;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;


class FileMailbox implements Mailbox{
    private Map<String/*uuid*/, Long/*filesize*/> mailMap = new Hashtable<>();
    private File directory;
    
    public FileMailbox(String directory) {
        this.directory = new File(directory);
        if (!this.directory.exists() && !this.directory.mkdir()) {
            System.err.println("Verzeichnis " + directory + " konnte nicht erstellt werden, Mailbox verwendet '.'");
            this.directory = new File("."); //If target directory can't be created, use working directory
        }
        scanDirectory();
    }
    
    @Override
    public List<String> listMails() {
        return new ArrayList<>(mailMap.keySet());
    }

    @Override
    public List<String> listMailsWithout(Set<String> filter) {
        List<String> uuids = new ArrayList<>();
        for(String uuid : mailMap.keySet()) {
            if (!filter.contains(uuid))
                uuids.add(uuid);
        }
        return uuids;
    }

    @Override
    public synchronized String readMail(String uuid) {
        if (mailMap.containsKey(uuid)) {
            try {
                StringBuilder mailContent = new StringBuilder(1024);
                FileInputStream mailStream = new FileInputStream(getFile(uuid));
                byte[] buffer = new byte[256];
                int len;
                while ((len = mailStream.read(buffer)) > 0)
                    mailContent.append(new String(buffer, 0, len));
               
                mailStream.close();
                StringBuilder second = new StringBuilder(1024);
                for (String line : mailContent.toString().split("\r\n")) {
                    if (line.startsWith("."))
                        second.append(".");
                    second.append(line).append("\r\n");
                }
                return second.toString();
                    
            } catch (IOException e) {}
        } 
        return null;
    }

    @Override
    public synchronized void deleteMail(String uuid) {
        if (mailMap.containsKey(uuid)) {
            mailMap.remove(uuid);
            getFile(uuid).delete();
        }
    }

    @Override
    public synchronized void writeMail(String uuid, String content) {
        try {
            File mail = getFile(uuid);
            if (mail.exists()) {
                System.err.println("Mail " + uuid + " existiert bereits");
                return;
            }
            
            mail.createNewFile();
            try (FileOutputStream mailStream = new FileOutputStream(mail)) {
                mailStream.write(content.getBytes());
            }
            mailMap.put(uuid, (long)content.length());
        } catch (IOException e) {
            System.err.println("Mail " + uuid + " konnte nicht gespeichert werden");
        }
    }

    @Override
    public int size() {
        return mailMap.size();
    }

    @Override
    public long mailSize(String uuid) {
        return mailMap.get(uuid);
    }

    @Override
    public boolean containsMail(String uuid) {
        return mailMap.containsKey(uuid);
    }

    @Override
    public synchronized void writeMail(String uuid, List<String> lines) {
         try {
            File mail = getFile(uuid);
            if (mail.exists()) {
                System.err.println("Mail " + uuid + " existiert bereits");
                return;
            }
            
            mail.createNewFile();
            try (FileOutputStream mailStream = new FileOutputStream(mail)) {
                for(String line : lines) {
                    mailStream.write(line.getBytes());
                    mailStream.write("\r\n".getBytes());
                }
            }
            mailMap.put(uuid, mail.length());
        } catch (IOException e) {
            System.err.println("Mail " + uuid + " konnte nicht gespeichert werden");
        }
    }

    private void scanDirectory() {
        File[] files = directory.listFiles(MailFilter.instance);
        for(File tempFile : files)
            mailMap.put(tempFile.getName().replace(".mail", ""), tempFile.length());
    }

    private File getFile(String uuid) {
        String path = directory.getAbsolutePath();
        return new File(path + "/" + uuid + ".mail");
    }
}

class MailFilter implements FilenameFilter {
    static MailFilter instance = new MailFilter();
    
    @Override
    public boolean accept(File dir, String name) {
        return name.endsWith(".mail");
    }
}
